#include "updater.h"
#include "ui_updater.h"

Updater::Updater(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Updater)
    , m_db()
    , m_manager(new QNetworkAccessManager)
    , m_reply(nullptr)
{
    ui->setupUi(this);
}

Updater::~Updater()
{
    delete ui;
}

void Updater::downloadAndUpdate()
{
    if (m_reply->error() == QNetworkReply::NoError)
    {
        QUrl downloadUrl = m_reply->url();
        QString fileName = downloadUrl.fileName();

        QString tempDir = QDir::tempPath();
        QString newExePath = tempDir + "/" + fileName;

        // 保存下载的文件到临时路径
        QFile file(newExePath);
        if (file.open(QIODevice::WriteOnly))
        {
            file.write(m_reply->readAll());
            file.close();
            qDebug() << "新版本下载成功，保存到:" << newExePath;
            newExePath = QDir::toNativeSeparators(newExePath);

            QString command = QString(R"(
                @echo off
                chcp 65001

                set TAR_FILE="%1"
                set EXTRACTED_FOLDER="%2"
                set TOTAL_FILES=0

                for /f "tokens=*" %%A in ('tar -tzf %TAR_FILE% ^| find /c /v ""') do set TOTAL_FILES=%%A

                start /b tar -xzf %TAR_FILE% -C %EXTRACTED_FOLDER% -U

                :loop
                if exist %EXTRACTED_FOLDER% (
                    for /f %%A in ('dir %EXTRACTED_FOLDER% /s /b ^| find /c /v ""') do set FILE_COUNT=%%A
                    set /a PROGRESS=FILE_COUNT*100/TOTAL_FILES
                    cls
                    echo 解压更新进度：%PROGRESS%%%
                    echo 剩余文件: %FILE_COUNT% / %TOTAL_FILES%)%
                    if %FILE_COUNT% LSS %TOTAL_FILES% goto loop
                )

                cls
                echo "更新完成，3 秒后关闭将关闭此窗口"
                timeout /t 3
                del "%3"
                del "%~f0"
            )").arg(QDir::toNativeSeparators(newExePath)).arg(QCoreApplication::applicationDirPath()).arg(QDir::toNativeSeparators(newExePath));

            // 保存到批处理文件
            QString batFilePath = QCoreApplication::applicationDirPath() + "/extract.bat";
            QFile batFile(batFilePath);
            if (batFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&batFile);
                out << command;        // 写入命令
                batFile.close();
            } else {
                qDebug() << "无法创建批处理文件：" << batFilePath;
                return;
            }

            // 解压路径：当前程序目录下
            QString batCommand = QString("cmd.exe /C \"%1\"").arg(QDir::toNativeSeparators(batFilePath));
            std::wstring wCommand = batCommand.toStdWString();
            STARTUPINFOW si = { sizeof(si) };
            PROCESS_INFORMATION pi;
            if (CreateProcessW(NULL, (LPWSTR)wCommand.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);
            }

            QCoreApplication::exit(0);
        }
        else {
            qDebug() << "无法保存新版本文件到:" << newExePath;
        }
    }
    else {
        qDebug() << "下载失败:" << m_reply->errorString();
        QMessageBox::critical(this, "下载失败", "更新文件下载失败：" + m_reply->errorString());
        QCoreApplication::exit(0);
    }

    m_reply->deleteLater();
}


// 检查更新
void Updater::checkUpdate()
{
    QSqlQuery query = m_db.selectData("application", "*", QString("game_id = %1").arg(Config::instance().gameId()));

    if (query.next())
    {
        QString remoteFileName = query.value("version").toString();
        qDebug() << "远程版本:" << remoteFileName;

        QString localVersion = Config::instance().gameVersion();
        qDebug() << "本地版本:" << localVersion;

        if (isVersionHigher(remoteFileName, localVersion))
        {
            // 有新版本，去下载
            QString src = query.value("src").toString();
            QUrl url(QString("%1%2").arg(Config::instance().updateUrl()).arg(src));
            QNetworkRequest request(url);
            m_reply = m_manager->get(request);

            QObject::connect(m_reply, &QNetworkReply::errorOccurred, this, [=](QNetworkReply::NetworkError code) {
                qDebug() << "网络错误:" << code;
                QMessageBox::critical(this, "下载失败", "更新文件下载失败：网络错误:");
                QCoreApplication::exit(0);
            });
            QObject::connect(m_reply, &QNetworkReply::finished, this, &Updater::downloadAndUpdate);
            QObject::connect(m_reply, &QNetworkReply::downloadProgress, this, [=](qint64 bytesReceived, qint64 bytesTotal) {
                if (bytesTotal > 0) {
                    ui->progressBar->setRange(0, 100);
                    int percent = static_cast<int>((bytesReceived * 100) / bytesTotal);
                    ui->progressBar->setValue(percent);
                    ui->label->setText("正在下载");
                }
            });
        }
        else {
            emit updateFinished();
        }
    }
    else {
        // 查询不到数据，直接进入主程序
        emit updateFinished();
    }
}

QVector<int> Updater::parseVersion(const QString &version) {
    QVector<int> result;
    // 移除前缀（如 "V"）并按点分割
    QString cleanedVersion = version.startsWith('V') ? version.mid(1) : version;
    QStringList parts = cleanedVersion.split('.');
    for (const QString& part : parts) {
        bool ok;
        int num = part.toInt(&ok);
        if (ok) {
            result.append(num);
        } else {
            result.append(0); // 如果解析失败，填入 0
        }
    }
    // 确保至少有 3 个部分（主版本、次版本、补丁版本）
    while (result.size() < 3) {
        result.append(0);
    }
    return result;
}

bool Updater::isVersionHigher(const QString &remoteVersion, const QString &localVersion) {
    QVector<int> remote = parseVersion(remoteVersion);
    QVector<int> local = parseVersion(localVersion);

    for (int i = 0; i < qMin(remote.size(), local.size()); ++i) {
        if (remote[i] > local[i]) {
            return true;
        } else if (remote[i] < local[i]) {
            return false;
        }
    }
    return false; // 如果所有部分相等，则不更新
}
